`timescale	1ps/1ps
module a3_mcu_top(
		//时钟和复位
                input	wire		resetb,
                input   wire		sclk,
                
		//jtag接口
		input	wire		JTRST,
		input	wire		JTCK,
		input	wire		JTDI,
		input	wire		JTMS,
		output	wire		JTDO,

		//flash接口
		output	reg		flash_CS_n,
		output	reg		flash_SCK,
		output	reg		flash_SI,
		input	wire		flash_SO,

		//内部配置总线
		output	wire		w_d_ok,
		output	wire	[29:0]	w_addr,
		output	wire	[31:0]	w_data,
		output	wire		r_flag,
		output	wire	[29:0]	r_addr,
		input	wire	[31:0]	r_data,
		
		//GPIO
		inout	tri	[7:0]	mcu_io_a,
		input	wire	[7:0]	mcu_in_b,
		output	wire	[7:0]	mcu_out_c,
		
		//GPIO
		output	wire		UART_TXD,
		input	wire		UART_RXD,

		//PHY初始化
		output	reg		phy_rst,
		output	reg		phy_mdc,
		inout	tri		phy_mdio,
		
		//FPGA模块Flash控制
		input	wire		fpga_f_CS_n,
		input	wire		fpga_f_SCK,
		input	wire		fpga_f_SI,
		output	wire		fpga_f_SO,

		//FPGA模块PHY控制
		input	wire		fpga_phy_rst,
		input	wire		fpga_phy_mdc,
		input	wire		fpga_mdio_oe,
		input	wire		fpga_mdio_o,
		output	wire		fpga_mdio_i,

		//调试信号
		output	wire	[31:0]	tout
		);

//**********************************************/
//        	信号定义
/***********************************************/
reg		mcu_clk;

wire	[1:0]	hresp, htrans;
wire	[2:0]	hsize;
wire		hwrite, hsel, hready;
wire	[31:0]	haddr, hwdata, hrdata;

wire	[7:0]	GPIO0_I, GPIO0_O, nGPEN0;
wire	[7:0]	GPIO1_I, GPIO1_O, nGPEN1;
wire	[7:0]	GPIO2_I, GPIO2_O, nGPEN2;

wire	[31:0]	core_tout;

wire		mcu_f_CS_n, mcu_f_SCK, mcu_f_SI, mcu_f_SO;

wire		mcu_init;
reg		flash_ctrl_mcu, phy_ctrl_mcu;		
reg		mdio_oe, mdio_o;

wire	[31:0]	ahb_tout;
//**********************************************/
//        	mcu时钟
/***********************************************/
always @(posedge sclk)
	mcu_clk <= ~mcu_clk;

//**********************************************/
//        	mcu相关模块
/***********************************************/
//MCU内核
mcu_agm_core    mcu_core(
		//时钟和复位
    		.resetb			(resetb),
		.mcu_clk		(mcu_clk),
 
 		//初始化标志
		.init_flag		(mcu_init),
		
		//JTAG调试
    		.JTRST                  (JTRST),
    		.JTCK                   (JTCK),
    		.JTDI                   (JTDI),
    		.JTMS			(JTMS),
    		.JTDO                   (JTDO),
 
		//Flash接口
    		.FLASH_BIAS             (24'hB2000),
    		.FLASH_CS_n             (mcu_f_CS_n),
		.FLASH_SCK              (mcu_f_SCK),
    		.FLASH_SI		(mcu_f_SI),
    		.FLASH_SO		(mcu_f_SO),

		//共享RAM接口
    		.EXT_RAM_EN             (EXT_RAM_EN),
    		.EXT_RAM_WR             (EXT_RAM_WR),
    		.EXT_RAM_ADDR           (EXT_RAM_ADDR),
    		.EXT_RAM_BYTE_EN        (EXT_RAM_BYTE_EN),
    		.EXT_RAM_WDATA          (EXT_RAM_WDATA),
    		.EXT_RAM_RDATA          (EXT_RAM_RDATA),
 
		//AHB接口
    		.htrans			(htrans),
    		.hsize			(hsize),
		.hsel			(hsel),
		.hwrite			(hwrite),
    		.haddr			(haddr),
		.hwdata			(hwdata),
    		.hrdata			(hrdata),
   		.hresp			(hresp),//2'b00),
    		.hready			(hready),//1'b1),

  		//串口
   		.UART_RXD               (UART_RXD),
    		.UART_TXD               (UART_TXD),

  		//GPIO
    		.GPIO0_I                (GPIO0_I),
    		.GPIO0_O                (GPIO0_O),
    		.nGPEN0                 (nGPEN0),
    		.GPIO1_I                (GPIO1_I),
    		.GPIO1_O                (GPIO1_O),
    		.nGPEN1                 (nGPEN1),
    		.GPIO2_I                (GPIO2_I),
    		.GPIO2_O                (GPIO2_O),
    		.nGPEN2                 (nGPEN2),
    		
    		.tout               	(core_tout)
		);

//**************************************************************
//        		控制选通
//**************************************************************
//选通信号
always @(posedge sclk or negedge resetb)
	if (resetb == 0) begin
		flash_ctrl_mcu <= 0;
		phy_ctrl_mcu <= 0;
		end
	else if (w_d_ok == 1)
		case (w_addr)
			30'h2001_8000: flash_ctrl_mcu <= w_data[0];
			30'h2001_8004: phy_ctrl_mcu <= w_data[0];
		endcase

//Flash控制选通
always @( * )
	if ((mcu_init == 1) || (flash_ctrl_mcu == 1)) begin
		flash_CS_n	<= mcu_f_CS_n;
		flash_SCK	<= mcu_f_SCK;
		flash_SI	<= mcu_f_SI;
		end
	else begin
		flash_CS_n	<= fpga_f_CS_n;
		flash_SCK	<= fpga_f_SCK;
		flash_SI	<= fpga_f_SI;
		end
		
assign	mcu_f_SO = flash_SO;
assign	fpga_f_SO = flash_SO;

//PHY控制选通
always @(posedge sclk)
	if (phy_ctrl_mcu == 0) begin
		phy_rst <= fpga_phy_rst;
		phy_mdc <= fpga_phy_mdc;
		mdio_oe <= fpga_mdio_oe;
		mdio_o <= fpga_mdio_o;
		end
	else begin
		phy_rst <= GPIO0_O[0];
		phy_mdc <= GPIO0_O[1];
		mdio_oe <= ~nGPEN0[2];
		mdio_o <= GPIO0_O[2];
		end

//**************************************************************
//        		AHB总线
//**************************************************************
mcu_ahb_bud u_ahb_bud(
		//时钟,复位
    		.resetb		(resetb),
		.mcu_clk	(mcu_clk),
		.sclk		(sclk),
		
 		//初始化标志
		.mcu_init	(mcu_init),

		//ext ahb
    		.htrans		(htrans),
    		.hsize		(hsize),
		.hsel		(hsel),
		.hwrite		(hwrite),
    		.haddr		(haddr),
		.hwdata		(hwdata),
    		.hrdata		(hrdata),
   		.hresp		(hresp),
    		.hready		(hready),

		//内部总线
		.w_d_ok		(w_d_ok),
    		.w_addr		(w_addr),
		.w_data		(w_data),
    		.r_flag		(r_flag),
   		.r_addr		(r_addr),
    		.r_data		(r_data),
						
		//调试信号
    		.tout           (ahb_tout)
		);

//**************************************************************
//        		GPIO
//**************************************************************
assign	mcu_io_a[0] = (nGPEN0[0] == 0)? 	GPIO0_O[0]	:1'bz;
assign	mcu_io_a[1] = (nGPEN0[1] == 0)? 	GPIO0_O[1]	:1'bz;
assign	mcu_io_a[2] = (nGPEN0[2] == 0)? 	GPIO0_O[2]	:1'bz;
assign	mcu_io_a[3] = (nGPEN0[3] == 0)? 	GPIO0_O[3]	:1'bz;
assign	mcu_io_a[4] = (nGPEN0[4] == 0)? 	GPIO0_O[4]	:1'bz;
assign	mcu_io_a[5] = (nGPEN0[5] == 0)? 	GPIO0_O[5]	:1'bz;
assign	mcu_io_a[6] = (nGPEN0[6] == 0)? 	GPIO0_O[6]	:1'bz;
assign	mcu_io_a[7] = (nGPEN0[7] == 0)? 	GPIO0_O[7]	:1'bz;

//Port A, 双向IO
//assign	GPIO0_I[1:0] = mcu_io_a[1:0];
//assign	GPIO0_I[7:3] = mcu_io_a[7:3];
//Port B, 输入用
assign	GPIO1_I = mcu_in_b;
//Port C, 输出用
assign	mcu_out_c = GPIO2_O;

//**************************************************************
//        		PHY双向驱动
//**************************************************************
assign phy_mdio = (mdio_oe == 1) ? mdio_o : 1'bz;
assign fpga_mdio_i = phy_mdio;
assign GPIO0_I[2] = phy_mdio;

//**************************************************************
//        		调试信号
//**************************************************************
//assign tout = {hsize, hresp, htrans, hsel, hready, hwrite, flash_ctrl_mcu, phy_ctrl_mcu, GPIO0_I[2], phy_mdc, phy_rst};
assign tout = {ahb_tout[3], hsize, w_addr[29:28], htrans, hsel, hready, hwrite, flash_ctrl_mcu, phy_ctrl_mcu, ahb_tout[2:0]};

endmodule
